﻿using System;
using System.ComponentModel;
using System.Deployment.Application;
using System.Globalization;
using System.Windows.Forms;

namespace Bing_Wallpaper_Downloader
{
    class ClickOnce
    {
        public static void CheckForUpdate()
        {
            using (BackgroundWorker ClickOnce_BackgroundWorker = new BackgroundWorker())
            {
                ClickOnce_BackgroundWorker.DoWork += new DoWorkEventHandler(ClickOnceUpdater_DoWork);
                ClickOnce_BackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ClickOnceUpdater_RunWorkerCompleted);
                ClickOnce_BackgroundWorker.RunWorkerAsync();
            }
        }

        private enum ClickOnceStatus
        {
            NoUpdateAvailable,
            UpdateAvailable,
            UpdateRequired,
            NotDeployedViaClickOnce,
            DeploymentDownloadException,
            InvalidDeploymentException,
            InvalidOperationException
        }

        private static void ClickOnceUpdater_DoWork(object sender, DoWorkEventArgs e)
        {
            UpdateCheckInfo info = null;

            if (ApplicationDeployment.IsNetworkDeployed == false)
            {
                e.Result = ClickOnceStatus.NotDeployedViaClickOnce;

                return;
            }

            ApplicationDeployment updateCheck = ApplicationDeployment.CurrentDeployment;

            try
            {
                info = updateCheck.CheckForDetailedUpdate();
            }
            catch (Exception ex)
            {
                switch (ex.GetType().ToString())
                {
                    case "DeploymentDownloadException":
                        e.Result = ClickOnceStatus.DeploymentDownloadException;

                        return;
                    case "InvalidDeploymentException":
                        e.Result = ClickOnceStatus.InvalidDeploymentException;

                        return;
                    case "InvalidOperationException":
                        e.Result = ClickOnceStatus.InvalidOperationException;

                        return;
                    default:
                        break;
                }
            }

            if (info.UpdateAvailable == true)
            {
                if (info.IsUpdateRequired == true)
                {
                    e.Result = ClickOnceStatus.UpdateRequired;
                }
                else
                {
                    e.Result = ClickOnceStatus.UpdateAvailable;
                }
            }
            else
            {
                e.Result = ClickOnceStatus.NoUpdateAvailable;
            }
        }

        private static void ClickOnceUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            switch ((ClickOnceStatus)e.Result)
            {
                case ClickOnceStatus.NoUpdateAvailable:
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "No {0} update available.", Application.ProductName), Application.ProductName, MessageBoxButtons.OK);

                    break;
                case ClickOnceStatus.UpdateAvailable:
                    UpdateCheckInfo info = ApplicationDeployment.CurrentDeployment.CheckForDetailedUpdate();

                    if (MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "Would you like to update to {0} version {1} ({2} bytes)?", Application.ProductName, info.AvailableVersion, info.UpdateSizeBytes), Application.ProductName, MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        ClickOnceUpdate();
                    }

                    break;
                case ClickOnceStatus.UpdateRequired:
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "A required {0} update is available, it will now be updated.", Application.ProductName), Application.ProductName, MessageBoxButtons.OK);

                    ClickOnceUpdate();

                    break;
                case ClickOnceStatus.NotDeployedViaClickOnce:
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "{0} is not deployed via network.", Application.ProductName), Application.ProductName, MessageBoxButtons.OK);

                    break;
                case ClickOnceStatus.DeploymentDownloadException:
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "Error downloading {0} updates, please try again later.", Application.ProductName), Application.ProductName, MessageBoxButtons.OK);

                    break;
                case ClickOnceStatus.InvalidDeploymentException:
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "The {0} installation is corrupted. A manual repair is required.", Application.ProductName), Application.ProductName, MessageBoxButtons.OK);

                    break;
                case ClickOnceStatus.InvalidOperationException:
                    MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "Error updating {0}.", Application.ProductName), Application.ProductName, MessageBoxButtons.OK);

                    break;
                default:
                    break;
            }
        }

        private static void ClickOnceUpdate()
        {
            try
            {
                ApplicationDeployment updateCheck = ApplicationDeployment.CurrentDeployment;

                updateCheck.Update();

                MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "{0} has been upgraded, and will now restart.", Application.ProductName), Application.ProductName);

                Application.Restart();
            }

            catch
            {
                MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "Error performing {0} update!", Application.ProductName), Application.ProductName);

                return;
            }
        }
    }
}
